package syntax;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

import symbols.Symbol;

public class ProxyTerm  implements Comparable {
	private ArrayList<ProxyTerm> and_or;
	private ArrayList<Symbol> constants;
	private ArrayList<Symbol> nots;
	private ArrayList<Relation> some;
	private ArrayList<Relation> all;
	/**
	 * @param ors
	 * @param constants
	 * @param nots
	 * @param some
	 * @param all
	 */
	public ProxyTerm(ArrayList<ProxyTerm> and_or, ArrayList<Symbol> constants, ArrayList<Symbol> nots, ArrayList<Relation> some, ArrayList<Relation> all) {
		this.and_or = and_or;
		this.constants = constants;
		this.nots = nots;
		this.some = some;
		this.all = all;
	}
	
	public ProxyTerm(ProxyTerm arg) {
		// TODO Auto-generated constructor stub
	}

	public boolean ChackConsistency()  {
		ListIterator<Symbol> iter1 = constants.listIterator();
		ListIterator<Symbol> iter2 = nots.listIterator();
		
		
		try  {
			Symbol s1 = iter1.next();
			Symbol s2 = iter2.next();
			
			while(true)  {
				int i1 = s1.getId();
				int i2 = s2.getId();
			
				if(i1 < i2)  {
					s1 = iter1.next();
				}
				else  {
					if(i1 == i2)  {
						return false;
					}
					else  {
						s2 = iter2.next();
					}
				}
			}
		}
		catch(NoSuchElementException exception)  {
			return true;
		}	
	}
	
	
	public List<ProxyTerm> applyOrRule() {
		ArrayList<ProxyTerm> res = new ArrayList<ProxyTerm>();
		
		if(and_or.isEmpty()) return res;
		
		for(ProxyTerm term : and_or)  {
			ArrayList<ProxyTerm> new_and_or = term.and_or;
			ArrayList<Symbol> new_constants = new ArrayList<Symbol>(constants.size() + term.constants.size());
			ArrayList<Symbol> new_nots = new ArrayList<Symbol>(nots.size() + term.nots.size());
			ArrayList<Relation> new_some = new ArrayList<Relation>(some.size() + term.some.size());
			ArrayList<Relation> new_all = new ArrayList<Relation>(some.size() + term.some.size());
			
			new_constants.addAll(constants);
			new_constants.addAll(term.constants);
			new_nots.addAll(nots);
			new_nots.addAll(term.nots);
			new_some.addAll(some);
			new_some.addAll(term.some);
			new_all.addAll(all);
			new_all.addAll(term.all);
			
			ProxyTerm proxy = new ProxyTerm(new_and_or, new_constants, new_nots, new_some, new_all);
			proxy.sortAll();
			
			res.add(proxy);
			
		}
	
		return res;
		
	}
	
	private void add(ArrayList<ProxyTerm> and_or, ArrayList<Symbol> constants, ArrayList<Symbol> nots, ArrayList<Relation> some, ArrayList<Relation> all) {
		this.and_or.addAll(and_or);
		this.constants.addAll(constants);
		this.nots.addAll(nots);
		this.some.addAll(some);
		this.all.addAll(all);
	}
	
	private void add(ProxyTerm arg) {
		add(arg.and_or, arg.constants, arg.nots, arg.some, arg.all);
	}
	
	private void sortAll()  {
		Collections.sort(and_or);
		Collections.sort(constants);
		Collections.sort(nots);
		Collections.sort(some);
		Collections.sort(all);
	}
	
	public List<ProxyTerm> applyExistentialRule(ProxyTerm tbox)  {
		List<ProxyTerm> res = new LinkedList<ProxyTerm>();
		
		if(some.isEmpty()) return res;
		
		//ListIterator<Relation> iter = all.listIterator(); 
		for(Relation relS : some)  {
			Symbol name = relS.name;
			ProxyTerm term = new ProxyTerm(relS.arg);  // uwaga na pzekazywane kolekcje do konstruktorow
		
			ListIterator<Relation> iter = all.listIterator(); 
			while(iter.hasNext()) {
				Relation relA = iter.next();
				int f = relA.name.compareTo(name);
				if(f > 0)  {
					//iter.previous();
					break;
				}
				if(f == 0)  {
					ProxyTerm arg = relA.arg;
					term.add(arg);
				}
			}
			term.add(tbox);
			term.sortAll();
			res.add(term);
		}
		
		return res;
		
		
	}
	

	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return 0;
	}
}
